{# SPDX-License-Identifier: Apache-2.0 -#}
{% extends "manage_base.html" %}
{% set user = request.user %}
{% set title = gettext("Activate your account") %}
{% set active_tab = "account" %}
{% block title %}
  {{ title }}
{% endblock title %}
{% macro email_verification_label(email) -%}
  {% if email.verified %}
    {% if email.transient_bounces %}
      <span class="badge badge--warning">
        <i class="fa fa-exclamation-triangle" aria-hidden="true"></i>
        {% trans %}Verified*{% endtrans %}
      </span>
      <span class="table__status-detail">{% trans %}*Intermittent delivery problems may lead to verification loss{% endtrans %}</span>
    {% else %}
      <span class="badge badge--success">
        <i class="fa fa-check" aria-hidden="true"></i>
        {% trans %}Verified{% endtrans %}
      </span>
    {% endif %}
  {% else %}
    {% if email.unverify_reason.value == "spam complaint" %}
      <span class="badge badge--danger">
        <i class="fa fa-ban" aria-hidden="true"></i>
        {% trans %}Unverified*{% endtrans %}
      </span>
      <span class="table__status-detail">{% trans %}*Email from PyPI being treated as spam{% endtrans %}</span>
    {% elif email.unverify_reason.value == "hard bounce" %}
      <span class="badge badge--danger">
        <i class="fa fa-ban" aria-hidden="true"></i>
        {% trans %}Unverified*{% endtrans %}
      </span>
      <span class="table__status-detail">{% trans %}*Hard failure during delivery{% endtrans %}</span>
    {% elif email.unverify_reason.value == "soft bounce" %}
      <span class="badge badge--danger">
        <i class="fa fa-ban" aria-hidden="true"></i>
        {% trans %}Unverified*{% endtrans %}
      </span>
      <span class="table__status-detail">{% trans %}*Too many delivery problems{% endtrans %}</span>
    {% else %}
      <span class="badge badge--danger">
        <i class="fa fa-times" aria-hidden="true"></i>
        {% trans %}Unverified{% endtrans %}
      </span>
    {% endif %}
  {% endif %}
{% endmacro %}
{% macro email_row(email) -%}
  <tr>
    <td class="table__email" scope="row">{{ email.email }}</td>
    <td>
      <span class="table__status-badges">
        {% if email.primary %}
          <span class="badge">{% trans %}Primary{% endtrans %}</span>
        {% endif %}
        {{ email_verification_label(email) }}
      </span>
    </td>
    <td class="table__align-right">
      {% if not email.verified or not email.primary %}
        <nav class="dropdown dropdown--with-icons dropdown--wide">
          <button type="button"
                  class="button button--primary dropdown__trigger"
                  aria-haspopup="true"
                  aria-expanded="false"
                  aria-label="{% trans %}View email options{% endtrans %}">
            {% trans %}Options{% endtrans %}
            <span class="dropdown__trigger-caret">
              <i class="fa fa-caret-down" aria-hidden="true"></i>
            </span>
          </button>
          <ul class="dropdown__content"
              aria-hidden="true"
              aria-label="{% trans email=email.email %}Options for {{ email }}{% endtrans %}">
            {% if not email.verified %}
              <li>
                <form method="post">
                  <input hidden name="reverify_email_id" value="{{ email.id }}">
                  <input name="csrf_token"
                         type="hidden"
                         value="{{ request.session.get_csrf_token() }}">
                  <button type="submit"
                          class="dropdown__link"
                          title="{% trans %}Resend verification email{% endtrans %}">
                    <i class="fa fa-envelope" aria-hidden="true"></i>
                    {% trans %}Resend verification email{% endtrans %}
                  </button>
                </form>
              </li>
            {% endif %}
            {% if user.has_two_factor and not email.primary and email.verified %}
              {# Only permit primary changes if the user has 2FA #}
              <li>
                <form method="post">
                  <input hidden name="primary_email_id" value="{{ email.id }}">
                  <input name="csrf_token"
                         type="hidden"
                         value="{{ request.session.get_csrf_token() }}">
                  <button type="submit"
                          class="dropdown__link"
                          title="{% trans %}Set this email address as primary{% endtrans %}">
                    <i class="fa fa-cog" aria-hidden="true"></i>
                    {% trans %}Set as primary{% endtrans %}
                  </button>
                </form>
              </li>
            {% endif %}
          </ul>
        </nav>
      {% endif %}
    </td>
  </tr>
{%- endmacro %}
{% macro api_row(macaroon) -%}
  <tr>
    <th scope="row">
      <span class="table__mobile-label">{% trans %}Name{% endtrans %}</span>
      {{ macaroon.description }}
    </th>
    <td>
      <span class="table__mobile-label">{% trans %}Scope{% endtrans %}</span>
      {% if macaroon.permissions_caveat.permissions == 'user' %}
        {% trans %}All projects{% endtrans %}
      {% else %}
        {% for project in macaroon.permissions_caveat.get("permissions")['projects'] %}
          <a href="{{ request.route_path('packaging.project', name=project) }}">{{ project }}</a>
        {% endfor %}
      {% endif %}
    </td>
    <td>
      <span class="table__mobile-label">{% trans %}Created{% endtrans %}</span>
      {{ humanize(macaroon.created) }}
    </td>
    <td>
      <span class="table__mobile-label">{% trans %}Last used{% endtrans %}</span>
      {{ humanize(macaroon.last_used) if macaroon.last_used else gettext("Never") }}
    </td>
    <td class="table__align-right">
      <nav class="dropdown dropdown--with-icons dropdown--wide">
        <button type="button"
                class="button button--primary dropdown__trigger"
                aria-haspopup="true"
                aria-expanded="false"
                aria-label="{% trans %}View token options{% endtrans %}">
          {% trans %}Options{% endtrans %}
          <span class="dropdown__trigger-caret">
            <i class="fa fa-caret-down" aria-hidden="true"></i>
          </span>
        </button>
        <ul class="dropdown__content">
          <li>
            <a href="#remove-API-token--{{ macaroon.id }}" class="dropdown__link">
              <i class="fa fa-trash-alt" aria-hidden="true"></i>
              {% trans %}Remove token{% endtrans %}
            </a>
          </li>
          <li>
            <a href="#view-identifier--{{ macaroon.id }}" class="dropdown__link">
              <i class="fa fa-hashtag" aria-hidden="true"></i>
              {% trans %}View unique identifier{% endtrans %}
            </a>
          </li>
        </ul>
      </nav>
      {# modal to remove token #}
      {% set slug = "remove-API-token--" + macaroon.id | string %}
      {% set title = gettext("Remove API token") + " - " + macaroon.description %}
      {% set action = request.route_path('manage.account.token') %}
      {% set confirm_button_label = gettext("Remove API token") %}
      {% set extra_fields %}
        <input type="hidden"
               name="macaroon_id"
               value="{{ macaroon.id }}"
               autocomplete="off">
      {% endset %}
      {% set token_warning_text %}
        <p>{% trans %}Applications or scripts using this token will no longer have access to PyPI.{% endtrans %}</p>
      {% endset %}
      {{ confirm_password_modal(title=title, confirm_button_label=confirm_button_label, slug=slug, extra_fields=extra_fields, action=action, custom_warning_text=token_warning_text) }}
      {# modal to view token ID #}
      <div id="view-identifier--{{ macaroon.id }}" class="modal">
        <div class="modal__content" role="dialog">
          <a href="#modal-close"
             title="{% trans %}Close{% endtrans %}"
             class="modal__close">
            <i class="fa fa-times" aria-hidden="true"></i>
            <span class="sr-only">{% trans %}Close{% endtrans %}</span>
          </a>
          <div class="modal__body">
            <h3 class="modal__title">
              {% trans token_description=macaroon.description %}Unique identifier for API token "{{ token_description }}"{% endtrans %}
            </h3>
            <p>
              <code>{{ macaroon.id }}</code>
            </p>
            <button type="button"
                    class="button copy-tooltip copy-tooltip-e"
                    data-tooltip-label="{% trans %}Copy to clipboard{% endtrans %}"
                    data-clipboard-text="{{ macaroon.id }}">{% trans %}Copy{% endtrans %}</button>
          </div>
          <div class="modal__footer">
            <a href="#modal-close" class="button button--primary modal__action">{% trans %}Close{% endtrans %}</a>
          </div>
        </div>
      </div>
    </td>
  </tr>
{%- endmacro %}
{% block main %}
  <h1 class="page-title">{{ title }}</h1>
  <div class="callout-block">
    {% if user.has_two_factor %}
      <p>
        {% trans %}
        You must verify an existing email address and make it your primary email address
        before making any other changes to your account.
      {% endtrans %}
    </p>
    <p>
      {% trans help_url=help_url %}
      If you cannot verify any email addresses listed,
      please see <a href="{{ help_url }}">{{ help_url }}</a>
      to recover access to your account.
    {% endtrans %}
  </p>
{% else %}
  <p>
    {% trans %}
    You must verify the primary email address listed below
    before making any other changes to your account.
  {% endtrans %}
</p>
<p>
  {% trans help_url=help_url %}
  If you cannot verify the primary email address listed,
  please see <a href="{{ help_url }}">{{ help_url }}</a>
  to recover access to your account.
{% endtrans %}
</p>
{% endif %}
</div>
<section id="account-emails">
  <h2 class="sub-title">{% trans %}Account emails{% endtrans %}</h2>
  <p>
    {% trans %} You must have at least one <span class="badge badge--success"><i class="fa fa-check" aria-hidden="true"></i> Verified</span> email address to activate your account.{% endtrans %}
  </p>
  {# Sort the emails as follows:
      * Primary email
      * Verified emails, sorted alphabetically
      * Unverified emails, sorted alphabetically
#}
  {% set sorted_emails = user.emails|sort(attribute="email")|sort(attribute="verified", reverse=true)|sort(attribute="primary", reverse=true) %}
  <table class="table table--emails">
    <caption class="sr-only">{% trans %}Emails associated with your account{% endtrans %}</caption>
    <thead>
      <tr>
        <th scope="col">{% trans %}Email address{% endtrans %}</th>
        <th scope="col">{% trans %}Status{% endtrans %}</th>
        <th></th>
      </tr>
    </thead>
    <tbody>
      {% for email in sorted_emails %}{{ email_row(email) }}{% endfor %}
    </tbody>
  </table>
</section>
<section id="account-events">
  <h2>{% trans %}Security history{% endtrans %}</h2>
  {% set recent_events = user.recent_events.all() %}
  {% if recent_events|length > 0 %}
    {% macro caveat_detail(caveat) -%}
      {% if "permissions" in caveat %}
        {% if caveat.permissions == "user" %}
          {% trans %}Token scope: entire account{% endtrans %}
        {% else %}
          {% trans project_name=caveat.permissions.projects[0] %}Token scope: Project {{ project_name }}{% endtrans %}
        {% endif %}
      {% elif "exp" in caveat %}
        {% trans exp=humanize(caveat.exp) %}Expires: {{ exp }}{% endtrans %}
      {% endif %}
    {%- endmacro %}
    {% macro event_summary(event) -%}
      {% if event.tag == EventTag.Account.AccountCreate %}
        <strong>{% trans %}Account created{% endtrans %}</strong>
      {% elif event.tag == EventTag.Account.LoginSuccess %}
        <strong>{% trans %}Logged in{% endtrans %}</strong>
        <br>
        <small>
          {% trans %}Two factor method:{% endtrans %}
          {% if event.additional.two_factor_method == None %}
            {% trans %}None{% endtrans %}
          {% elif event.additional.two_factor_method == "webauthn" %}
            {% if event.additional.two_factor_label %}<strong>"{{ event.additional.two_factor_label }}"</strong> -{% endif %}
            {% trans %}Security device (<abbr title="web authentication">WebAuthn</abbr>){% endtrans %}
          {% elif event.additional.two_factor_method == "totp" %}
            {% trans %}Authentication application (<abbr title="time-based one-time password">TOTP</abbr>){% endtrans %}
          {% elif event.additional.two_factor_method == "recovery-code" %}
            {% trans %}Recovery code{% endtrans %}
          {% endif %}
        </small>
      {% elif event.tag == EventTag.Account.LoginFailure %}
        <strong>{% trans %}Login failed{% endtrans %}</strong>
        {% if event.additional.auth_method %}
          {% if event.additional.auth_method == "basic" %}
            {% trans %}- Basic Auth (Upload endpoint){% endtrans %}
          {% endif %}
        {% endif %}
        <br>
        <small>
          {% trans %}Reason:{% endtrans %}
          {% if event.additional.reason == "invalid_password" %}
            {% trans %}Incorrect Password{% endtrans %}
          {% elif event.additional.reason == "invalid_totp" %}
            {% trans %}Invalid two factor (TOTP){% endtrans %}
          {% elif event.additional.reason == "invalid_webauthn" %}
            {% trans %}Invalid two factor (WebAuthn){% endtrans %}
          {% elif event.additional.reason == "invalid_recovery_code" %}
            {% trans %}Invalid two factor (Recovery code){% endtrans %}
          {% elif event.additional.reason == "burned_recovery_code" %}
            {% trans %}Invalid two factor (Recovery code){% endtrans %}
          {% else %}
            {{ event.additional.reason }}
          {% endif %}
        </small>
      {% elif event.tag == "account:reauthenticate:failure" %}
        <strong>{% trans %}Session reauthentication failed{% endtrans %}</strong>
        <br>
        <small>
          {% trans %}Reason:{% endtrans %}
          {% if event.additional.reason == "invalid_password" %}
            {% trans %}Incorrect Password{% endtrans %}
          {% else %}
            {{ event.additional.reason }}
          {% endif %}
        </small>
      {% elif event.tag == EventTag.Account.EmailAdd %}
        <strong>{% trans %}Email added to account{% endtrans %}</strong>
        <br>
        <small>{{ event.additional.email }}</small>
      {% elif event.tag == EventTag.Account.EmailRemove %}
        <strong>{% trans %}Email removed from account{% endtrans %}</strong>
        <br>
        <small>{{ event.additional.email }}</small>
      {% elif event.tag == EventTag.Account.EmailVerified %}
        <strong>{% trans %}Email verified{% endtrans %}</strong>
        <br>
        <small>{{ event.additional.email }}</small>
      {% elif event.tag == EventTag.Account.EmailReverify %}
        <strong>{% trans %}Email reverified{% endtrans %}</strong>
        <br>
        <small>{{ event.additional.email }}</small>
      {% elif event.tag == EventTag.Account.EmailPrimaryChange %}
        {% if event.additional.old_primary %}
          <strong>{% trans %}Primary email changed{% endtrans %}</strong>
          <br>
          <small>
            {% trans %}Old primary email:{% endtrans %} {{ event.additional.old_primary }}
            <br>
            {% trans %}New primary email:{% endtrans %} {{ event.additional.new_primary }}
          </small>
        {% else %}
          <strong>{% trans %}Primary email set{% endtrans %}</strong>
          <br>
          <small>{{ event.additional.new_primary }}</small>
        {% endif %}
      {% elif event.tag == EventTag.Account.EmailSent %}
        <strong>{% trans %}Email sent{% endtrans %}</strong>
        <br>
        <small>
          {% trans %}From:{% endtrans %} <span class="table__monospace">{{ event.additional.from_ }}</span>
          <br>
          {% trans %}To:{% endtrans %} <span class="table__monospace">{{ event.additional.to }}</span>
          <br>
          {% trans %}Subject:{% endtrans %} <span class="table__monospace">{{ event.additional.subject }}</span>
        </small>
      {% elif event.tag == EventTag.Account.PasswordResetRequest %}
        <strong>{% trans %}Password reset requested{% endtrans %}</strong>
      {% elif event.tag == EventTag.Account.PasswordResetAttempt %}
        <strong>{% trans %}Password reset attempted{% endtrans %}</strong>
      {% elif event.tag == EventTag.Account.PasswordReset %}
        <strong>{% trans %}Password successfully reset{% endtrans %}</strong>
      {% elif event.tag == EventTag.Account.PasswordChange %}
        <strong>{% trans %}Password successfully changed{% endtrans %}</strong>
      {% elif event.tag == EventTag.Account.PendingOIDCPublisherAdded %}
        <strong>Pending trusted publisher added</strong>
        <small>{% trans %}Project:{% endtrans %} {{ event.additional.project }}</small>
        {{ oidc_audit_event(event) }}
      {% elif event.tag == EventTag.Account.PendingOIDCPublisherRemoved %}
        <strong>Pending trusted publisher removed</strong>
        <small>{% trans %}Project:{% endtrans %} {{ event.additional.project }}</small>
        {{ oidc_audit_event(event) }}
      {% elif event.tag == EventTag.Account.TwoFactorMethodAdded %}
        <strong>{% trans %}Two factor authentication added{% endtrans %}</strong>
        <br>
        <small>
          {% if event.additional.method == "webauthn" %}
            {% trans %}Method: Security device (<abbr title="web authentication">WebAuthn</abbr>){% endtrans %}
            <br>
            {% trans %}Device name:{% endtrans %} {{ event.additional.label }}
          {% elif event.additional.method == "totp" %}
            {% trans %}Method: Authentication application (<abbr title="time-based one-time password">TOTP</abbr>){% endtrans %}
          {% endif %}
        </small>
      {% elif event.tag == EventTag.Account.TwoFactorMethodRemoved %}
        <strong>{% trans %}Two factor authentication removed{% endtrans %}</strong>
        <br>
        <small>
          {% if event.additional.method == "webauthn" %}
            {% trans %}Method: Security device (<abbr title="web authentication">WebAuthn</abbr>){% endtrans %}
            <br>
            {% trans %}Device name:{% endtrans %} {{ event.additional.label }}
          {% elif event.additional.method == "totp" %}
            {% trans %}Method: Authentication application (<abbr title="time-based one-time password">TOTP</abbr>){% endtrans %}
          {% endif %}
        </small>
      {% elif event.tag == EventTag.Account.RecoveryCodesGenerated %}
        <strong>{% trans %}Recovery codes generated{% endtrans %}</strong>
        <br>
      {% elif event.tag == EventTag.Account.RecoveryCodesRegenerated %}
        <strong>{% trans %}Recovery codes regenerated{% endtrans %}</strong>
        <br>
      {% elif event.tag == EventTag.Account.RecoveryCodesUsed %}
        <strong>{% trans %}Recovery code used for login{% endtrans %}</strong>
        <br>
      {% elif event.tag == EventTag.Account.APITokenAdded %}
        <strong>{% trans %}API token added{% endtrans %}</strong>
        <br>
        <small>
          {% trans %}Token name:{% endtrans %} {{ event.additional.description }}
          <br>
          {#
          NOTE: Old events contain a single caveat dictionary, rather than a list of caveats.

          This check can be deleted roughly 90 days after merge, since events older than
          90 days are not presented to the user.
        #}
          {% if event.additional.caveats is mapping %}
            {{ caveat_detail(event.additional.caveats) }}
          {% else %}
            {% for caveat in event.additional.caveats %}{{ caveat_detail(caveat) }}{% endfor %}
          {% endif %}
        </small>
      {% elif event.tag == EventTag.Account.APITokenRemoved %}
        <strong>{% trans %}API token removed{% endtrans %}</strong>
        <br>
        <small>{% trans %}Unique identifier:{% endtrans %} {{ event.additional.macaroon_id }}</small>
      {% elif event.tag == EventTag.Account.APITokenRemovedLeak %}
        <strong>{% trans %}API token automatically removed for security reasons{% endtrans %}</strong>
        <br>
        <small>
          {% trans %}Token name:{% endtrans %} {{ event.additional.description }}
          <br>
          {% trans %}Unique identifier:{% endtrans %} {{ event.additional.macaroon_id }}
          <br>
          {% if event.additional.permissions == "user" %}
            {% trans %}Token scope: entire account{% endtrans %}
          {% else %}
            {% trans project_name=event.additional.permissions.projects[0] %}Token scope: Project {{ project_name }}{% endtrans %}
          {% endif %}
          <br>
          {% trans public_url=event.additional.public_url %}Reason: Token found at <a href="{{ public_url }}">public url</a>{% endtrans %}
        </small>
      {% elif event.tag == EventTag.Account.OrganizationRoleInvite %}
        <strong>
          {% trans href=request.route_path('organizations.profile', organization=event.additional.organization_name), organization_name=event.additional.organization_name, role_name=event.additional.role_name|lower %}Invited to join <a href="{{ href }}">{{ organization_name }}</a>{% endtrans %}
        </strong>
      {% elif event.tag == EventTag.Account.OrganizationRoleDeclineInvite %}
        <strong>
          {% trans href=request.route_path('organizations.profile', organization=event.additional.organization_name), organization_name=event.additional.organization_name, role_name=event.additional.role_name|lower %}Invitation to join <a href="{{ href }}">{{ organization_name }}</a> declined{% endtrans %}
        </strong>
      {% elif event.tag == EventTag.Account.OrganizationRoleRevokeInvite %}
        <strong>
          {% trans href=request.route_path('organizations.profile', organization=event.additional.organization_name), organization_name=event.additional.organization_name, role_name=event.additional.role_name|lower %}Invitation to join <a href="{{ href }}">{{ organization_name }}</a> revoked{% endtrans %}
        </strong>
      {% elif event.tag == EventTag.Account.OrganizationRoleExpireInvite %}
        <strong>
          {% trans href=request.route_path('organizations.profile', organization=event.additional.organization_name), organization_name=event.additional.organization_name, role_name=event.additional.role_name|lower %}Invitation to join <a href="{{ href }}">{{ organization_name }}</a> expired{% endtrans %}
        </strong>
      {% else %}
        <strong>{{ event.tag }}</strong>
      {% endif %}
    {%- endmacro %}
    <p>
      {% trans faq_url=request.help_url(_anchor='suspicious-activity') %}
      Events appear here as security-related actions occur on your account. If you notice anything suspicious, please <a href="{{ faq_url }}">secure your account</a> as soon as possible.
    {% endtrans %}
  </p>
  <table class="table table--security-logs">
    <caption class="sr-only">{% trans %}Recent account activity{% endtrans %}</caption>
    <thead>
      <th scope="col">{% trans %}Event{% endtrans %}</th>
      <th scope="col">{% trans %}Time{% endtrans %}</th>
      <th scope="col">{% trans %}Additional Info{% endtrans %}</th>
    </thead>
    <tbody>
      {% for event in recent_events %}
        <tr>
          <td>{{ event_summary(event) }}</td>
          <td>
            <span class="table__mobile-label">{% trans %}Date / time{% endtrans %}</span>
            {{ humanize(event.time, time="true") }}
          </td>
          <td>
            <span class="table__mobile-label">{% trans %}Location Info{% endtrans %}</span>
            {{ "Redacted" if event.additional.redact_ip else event.location_info }}
            <br>
            <span class="table__mobile-label">{% trans %}Device Info{% endtrans %}</span>
            {{ event.user_agent_info }}
          </td>
        </tr>
      {% endfor %}
    </tbody>
  </table>
{% else %}
  <p>{% trans %}Events will appear here as security-related actions occur on your account.{% endtrans %}</p>
{% endif %}
</section>
{% endblock %}
{% block extra_js %}{% endblock %}
